package top.gytf.unifiedcall.model.response;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldNameConstants;
import org.springframework.lang.Nullable;
import top.gytf.unifiedcall.model.code.StatusCode;
import top.gytf.unifiedcall.model.code.builtin.BuiltinStatusCode;

import java.util.HashMap;
import java.util.Map;

/**
 * 统一响应体
 */
@FieldNameConstants
@RequiredArgsConstructor
public final class UnifiedResponse<T> {
    public static <T> UnifiedResponse<T> success() {
        return new UnifiedResponse<>(BuiltinStatusCode.SUCCESS, null, null);
    }

    public static <T> UnifiedResponse<T> success(@Nullable T data) {
        return new UnifiedResponse<>(BuiltinStatusCode.SUCCESS, null, data);
    }

    public static <T> UnifiedResponse<T> success(@Nullable String message) {
        return new UnifiedResponse<>(BuiltinStatusCode.SUCCESS, message, null);
    }

    public static <T> UnifiedResponse<T> success(@Nullable String message, @Nullable T data) {
        return new UnifiedResponse<>(BuiltinStatusCode.SUCCESS, message, data);
    }

    public static <T> UnifiedResponse<T> with(StatusCode code) {
        return new UnifiedResponse<>(code, null, null);
    }

    public static <T> UnifiedResponse<T> with(StatusCode code, @Nullable T data) {
        return new UnifiedResponse<>(code, null, data);
    }

    public static <T> UnifiedResponse<T> with(StatusCode code, @Nullable String message) {
        return new UnifiedResponse<>(code, message, null);
    }

    public static <T> UnifiedResponse<T> with(StatusCode code, @Nullable String message, @Nullable T data) {
        return new UnifiedResponse<>(code, message, data);
    }

    /**
     * 状态码
     */
    private final StatusCode code;

    /**
     * 响应信息
     */
    @Getter
    @Nullable
    private final String message;

    /**
     * 携带数据
     */
    @Getter
    @Nullable
    private final T data;

    /**
     * 附加数据
     */
    @Getter
    private final Map<String, String> metadata = new HashMap<>();

    /**
     * 内部使用的附加数据，不应该被序列化
     */
    private final Map<String, String> internalMetadata = new HashMap<>();

    @Nullable
    public String removeMetadata(String key) {
        return metadata.remove(key);
    }

    public void putMetadata(String key, String value) {
        metadata.put(key, value);
    }

    @Nullable
    public String getMetadata(String key) {
        return metadata.get(key);
    }

    @Nullable
    public String removeInternalMetadata(String key) {
        return internalMetadata.remove(key);
    }

    public void putInternalMetadata(String key, String value) {
        internalMetadata.put(key, value);
    }

    @Nullable
    public String getInternalMetadata(String key) {
        return internalMetadata.get(key);
    }

    public String getCode() {
        return code.value();
    }

    public StatusCode code() {
        return code;
    }
}
